#include "myThreadPool.h"
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>



struct ThreadPoolPrivate
{
    int minNum;             // 最小线程数量
    int maxNum;             // 最大线程数量
    int busyNum;            // 忙的线程的个数
    int liveNum;            // 存活的线程的个数
    int exitNum;            // 要销毁的线程个数
    int queueCapacity;  // 容量
    int queueSize;      // 当前任务个数
    int queueFront;     // 队头 -> 取数据
    int queueRear;      // 队尾 -> 放数据

    std::thread managerID;    // 管理者线程ID
 

    std::mutex mutexPool; // 锁整个的线程池
    std::mutex mutexBusy; // 锁busyNum变量

    std::condition_variable notFull;     // 任务队列是不是满了
    std::condition_variable notEmpty;    // 任务队列是不是空了

    std::vector<std::thread> workers;   // 工作的线程ID
    std::queue<std::function<void()>> tasks;

    bool isShutDown;     // 是不是要销毁线程池, 销毁为1, 不销毁为0
};

ThreadPool::ThreadPool(int minThreads, int maxThreads, int queueSize)
{
    p = new ThreadPoolPrivate;
    p->minNum = minThreads;
    p->maxNum = maxThreads;
    p->liveNum = minThreads;
    p->queueCapacity = queueSize;

    p->busyNum = 0;
    p->exitNum = 0;
    p->queueSize = 0;
    p->queueFront = 0;
    p->queueRear = 0;
    p->isShutDown = false;

    p->managerID = std::thread(&ThreadPool::managerThread, this);
    for(int i = 0; i < minThreads; i++)
    {
        p->workers.push_back(std::thread(&ThreadPool::workerThread,this));
    }
}

ThreadPool::~ThreadPool()
{
    if(p->isShutDown)
        delete p;
}

void ThreadPool::addTask(std::function<void()> task)
{
    std::unique_lock<std::mutex>lock(p->mutexPool);
    while(p->tasks.size() >= p->queueCapacity)
    {
        p->notFull.wait(lock);
    }
    p->tasks.push(task);
    p->queueSize++;
    p->notEmpty.notify_one();
}

void ThreadPool::stop() 
{
    if (!p->isShutDown) 
    {
        p->isShutDown = true;
        p->notEmpty.notify_all();
        for (auto& worker : p->workers) 
        {
            if (worker.joinable()) 
            {
                worker.join();
            }
        }
        if (p->managerID.joinable()) 
        {
            p->managerID.join();
        }
    }
}

void ThreadPool::workerThread() 
{
    std::function<void()> task;
    while (1) 
    {
        std::unique_lock<std::mutex> lock(p->mutexPool);
        while (p->tasks.empty() && !p->isShutDown) 
        {
            p->notEmpty.wait(lock);
        }
        if (p->isShutDown) 
        {
            break;
        }
        task = p->tasks.front();
        p->tasks.pop();
        p->queueSize--;
        p->notFull.notify_one();
        lock.unlock();

        task();
    }
}

void ThreadPool::managerThread() 
{
    while (!p->isShutDown) 
    {
        std::this_thread::sleep_for(std::chrono::seconds(3));
        std::unique_lock<std::mutex> lock(p->mutexPool);
        int queueSize = p->queueSize;
        int liveNum = p->liveNum;
        int busyNum = p->busyNum;
        lock.unlock();

        if (queueSize > liveNum && liveNum < p->maxNum) 
        {
            lock.lock();
            int addNum = 0;
            for (int i = 0; i < p->maxNum && addNum < p->maxNum && p->liveNum < p->maxNum; ++i) {
                if (p->workers[i].get_id() == std::thread::id()) 
                {
                    p->workers[i] = std::thread(&ThreadPool::workerThread, this);
                    addNum++;
                    p->liveNum++;
                }
            }
            lock.unlock();
        }

        if (busyNum * 2 < liveNum && liveNum > p->minNum) 
        {
            lock.lock();
            p->exitNum = p->minNum;
            lock.unlock();
            for (int i = 0; i < p->minNum; ++i) {
                p->notEmpty.notify_one();
            }
        }
    }
}